<?php

namespace app\common\model\virtual;

use app\common\loader\ModelMerchant;
use app\common\loader\ModelVirtual;
use app\common\model\BaseModel;
use app\home\loader\Model;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Exception;
use think\facade\Db;

/**
 * 虚码活动规则
 * Class VirtualPromo
 * @package app\common\model\virtual
 */
class VirtualPromoModel extends BaseModel
{
    //
    protected $name = 'virtual_promo';

    protected $json = ['union_rule', 'option', 'salesman'];

    // 分类ID
    public string $fieldId = 'id';
    // 商户ID
    public string $fieldMerId = 'mer_id';
    // 商品名称
    public string $fieldTitle = 'title';
    // 规则类型 1 单商品,2联合商品
    public string $fieldProductType = 'product_type';
    // 联合规则:{ sum: 0 ->合计数量, rule:-> 1: 全部满足 2,数量满足}
    public string $fieldUnionRule = 'union_rule';
    // 活动配置 :{ small_ticket:0->小票 1,需要 0 不需要, recheck_record:0 ->审核记录 1,需要 0 不需要 }
    public string $fieldOption = 'option';
    // 导购配置:{ red_packet:0.3->红包金额 point:0->积分数 day_num:0->日限制 }
    public string $fieldSalesman = 'salesman';
    // 总限制数量
    public string $fieldLimitNum = 'limit_num';
    // 已扫码数
    public string $fieldScannedNum = 'scanned_num';
    // 总红包总金额
    public string $fieldSumRedPacket = 'sum_red_packet';
    // 总积分数
    public string $fieldSumPoint = 'sum_point';
    // 备注
    public string $fieldMemo = 'memo';
    // 操作人
    public string $fieldOpUser = 'op_user';
    // 创建时间
    public string $fieldCreateAt = 'create_at';
    // 更新时间
    public string $fieldUpdateAt = 'update_at';
    //
    public string $fieldBeginTime = 'begin_time';
    //
    public string $fieldEndTime = 'end_time';
    // 状态 1 可以 0 禁用
    public string $fieldStatus = 'status';
    // 特殊规则数
    public string $fieldSpecialNum = 'special_num';
    // 绑定商品数
    public string $fieldProductNum = 'product_num';

    // 设置字段信息
    protected $schema = [
        'id' => 'int',        // 分类ID
        'mer_id' => 'string',        // 商户ID
        'title' => 'string',        // 商品名称
        'product_type' => 'int',        // 规则类型 1 单商品,2联合商品
        'union_rule' => 'json',        // 联合规则:{ sum: 0 ->合计数量, rule:-> 1: 全部满足 2,数量满足}
        'option' => 'json',        // 活动配置 :{ small_ticket:0->小票 1,需要 0 不需要, recheck_record:0 ->审核记录 1,需要 0 不需要 }
        'salesman' => 'json',        // 导购配置:{ red_packet:0.3->红包金额 point:0->积分数 day_num:0->日限制 }
        'limit_num' => 'int',        // 总限制数量
        'scanned_num' => 'int',        // 已扫码数
        'sum_red_packet' => 'float',        // 总红包总金额
        'sum_point' => 'int',        // 总积分数
        'memo' => 'string',        // 备注
        'op_user' => 'int',        // 操作人
        'create_at' => 'datetime',        // 创建时间
        'update_at' => 'datetime',        // 更新时间
        'begin_time' => 'datetime',        //
        'end_time' => 'datetime',        //
        'status' => 'int',        // 状态 1 可以 0 禁用
        'special_num' => 'int',        // 特殊规则数
        'product_num' => 'int',        // 绑定商品数
    ];

    /**
     * 获取活动上特殊规则和商品的数据
     * @param array $vpids
     * @return void
     */
    public function getSpecialAndProductCountInfo(array $vpids): array
    {
        $result = ['special' => [], 'product' => []];
        if (!empty($vpids)) {
            $result['special'] = ModelVirtual::VirtualPromoSpecial()->getNums($vpids);
            $result['product'] = ModelVirtual::VirtualPromoProduct()->getNums($vpids);
        }
        return $result;
    }

    /**
     * 更新扫码数量
     * @param     $id | 主键
     * @param     $scanned_num | 变化数量
     * @param int $type | 1增加， 2减少
     * @return mixed
     * @throws DbException|Exception
     */
    public function updateStockMarket($id, $scanned_num, int $type = 1)
    {
        return $this->db()->removeOption()->where('id', $id)
            ->update(['scanned_num' => Db::raw('scanned_num ' . ($type === 1 ? '+' : '-') . $scanned_num)]);
    }

    /**
     * 获取符合活动的商品的活动规格
     * @param $mer_id |商户id
     * @param $product_code |商品code
     * @param $field |需要获取的字段
     * @throws DbException
     * @throws Exception
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     */
    public function getVirtualPromoProduct($mer_id, $product_code, $user_id)
    {
        $date = date('Y-m-d');
        $activity = $this->db()->where(['status' => 1, 'mer_id' => $mer_id])
            ->where('begin_time', '<=', $date)
            ->where('end_time', '>=', $date)
            ->where('id', 'in', function ($query) use ($mer_id, $product_code) {
                $query->name('virtual_promo_product')
                    ->where(['mer_id' => $mer_id, 'product_code' => $product_code])
                    ->field('vp_id');
            })->json(['union_rule', 'option', 'salesman'])
            ->select();
        if (empty($activity)) {
            $prodcut_name = $this->db('product')->where('mer_id', $mer_id)->where('code', $product_code)->value('title');
            if (!empty($prodcut_name)) {
                ModelMerchant::MerchantInfo()->throwErrorMerchant($mer_id, API_EXCEPTION, '领取失败', [
                    0 => '获取条码：' . $product_code,
                    1 => '商品名称：' . $prodcut_name,
                    2 => '该商品活动已暂停；请截图或拍照后，联系供货商！',
                ]);
            }
            ModelMerchant::MerchantInfo()->throwErrorMerchant($mer_id, API_EXCEPTION, '领取失败', [
                0 => '获取条码：' . $product_code,
                1 => '商品不存在',
                2 => '请检查“获取条码”是否完整，确认条码完整后，请与供货商联系！',
            ]);
        }

        if (count($activity) === 1 && (int)$activity[0]['product_type'] === 1) {
            $activityData = Model::VirtualPromo()->getValidPromInfo(0, (int)$user_id, current($activity));
            $activity[0]['option']['small_ticket'] = $activityData['small_ticket'];
            $activity[0]['option']['recheck_record'] = $activityData['recheck_record'];
            $activity[0]['salesman']['red_packet'] = $activityData['red_packet'];
            $activity[0]['salesman']['point'] = $activityData['point'];
        }
        return $activity;
    }


    /**
     * 活动销量库存及小票
     * @param $salesman |导购配置
     * @param $shop_salesman_id |导购id
     * @param $virtual_id |活动id
     * @param $option |（小票活动配置）
     * @param $ticket |小票
     * @throws Exception
     */
    public function VirtualStockAndTicket($salesman, $shop_salesman_id, $virtual_id, $option, $ticket): void
    {

        if ($salesman['day_num'] !== 0 && $salesman['day_num'] <= $this->db('virtual_used_log')->where([
                'vp_id' => $virtual_id,
                'salesman_id' => $shop_salesman_id,
            ])->where('create_at', '>', date('Y-m-d H:i:s', strtotime("yesterday")))->count('id') + 1) {
            throw  new Exception('日限制数量已到上线', API_ERROR);
        }

        if ($option['small_ticket'] === 1 && empty($ticket)) {
            throw  new Exception('请上传小票', API_ERROR);
        }

    }


    /**
     *  根据类型,更新特殊规则或商品的数量
     * @param int $vpId 活动ID
     * @param int $type 类型 1: 特殊规格   2:商品
     * @param int $flag 标识 1:增加,  2:减少
     * @param int $num 变更数量: 默认为1
     * @return mixed
     * @throws DbException
     */
    public function updateSpecialAndProductNum(int $vpId, int $type, int $flag = 1, int $num = 1)
    {
        $field = ($type === 1 ? 'special_num' : 'product_num');
        $op = ($flag === 1 ? '+' : '-');
        return $this->db()->where('id', $vpId)->update([$field => Db::raw($field . $op . $num)]);
    }


    /**
     *  列表
     * @param array $where
     * @param int $limit
     * @return mixed
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getPromoList($where = [], $limit = 10)
    {
        $list = $this->db()->where($where)
            ->field('id,title,product_type,limit_num,scanned_num,sum_red_packet,
            sum_point,status,product_type as product_type_name ,
            option,salesman,union_rule')
            ->withAttr(['product_type_name' => function ($value) {
                $type = ['1' => '单商品', '2' => '联合商品'];
                return $type[$value];
            }])
            ->limit($limit)
            ->select();
        return $list;
    }
}
